/***************************************************************************
 * Copyright 2012 TXT e-solutions SpA
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * This work was performed within the IoT_at_Work Project
 * and partially funded by the European Commission's
 * 7th Framework Programme under the research area ICT-2009.1.3
 * Internet of Things and enterprise environments.
 *
 * Authors:
 *      Salvatore Piccione (TXT e-solutions SpA)
 *      Carbone Matteo
 *
 * Contributors:
 *        Domenico Rotondi (TXT e-solutions SpA)
 **************************************************************************/
package it.txt.ens.authorisationService.rabbitmq;

import it.txt.ens.authorisationService.gui.standalone.util.StandardOutStreamForwarder;

import java.io.File;
import java.io.IOException;
import java.util.Map;


/**
 * This class executes RabbitMQ commands. It requires the existence of the environment or
 * Java system variable <code>RABBITMQ_SERVER</code> whose value is the path of the installation folder
 * of the local RabbitMQ instance.
 * 
 * @author Carbone Matteo
 * @author Salvatore Piccione (TXT e-solutions SpA - salvatore.piccione AT network.txtgroup.com)
 *
 */
public class RabbitMQCommandExecutor {

    private static final String SET_PERMISSION_FORMAT = "\"%1$s\" \"%2$s\" \"%3$s\"";

	private String path = new String();

	public RabbitMQCommandExecutor() {
		setPath();
	}

	public String getPath() {
		return path;
	}

	public void setPath() {
		//SEARCH THE PATH AMONG THE ENVIRONMENT VARIABLES
		Map<String, String> env = System.getenv();
		String RABBITMQ_HOME_VARIANLE_NAME = "RABBITMQ_SERVER";
		String temp = null;
		// Read the path of script;
		for (String envName : env.keySet()) {
			if (envName.equals(RABBITMQ_HOME_VARIANLE_NAME)) {
				temp = env.get(envName);
			}
		}
		if (temp == null) {
			//SEARCH THE PATH AMONG THE JAVA PROPERTIES
			temp = System.getProperty(RABBITMQ_HOME_VARIANLE_NAME);
		}
		if (temp == null)
			throw new RuntimeException ("Please, define an environment variable or a Java property named \"" + 
					RABBITMQ_HOME_VARIANLE_NAME + "\" that points to the RabbitMQ Home!!!");
		this.path = temp;
	}

	// This method starts the server rabbitMQ
	public void startServer() throws IOException {

		File file = new File(path + "/rabbitmq-server.bat");
		String absPath = file.getAbsolutePath();
		if (absPath.contains(" "))
			absPath = "\"" + absPath + "\"";
		String[] command = { "cmd", "/c", /*"start",*/ absPath };
		//by doing this, RabbitMQ stops when closing the app
		try {
			Runtime runtime = Runtime.getRuntime();
			Process p = runtime.exec(command,null);
			runtime.addShutdownHook(new Thread(new Runnable() {
				
				public void run() {
					try {
						RabbitMQCommandExecutor.this.stopServer();
					} catch (IOException e) {
						System.err.println(e);
					}
				}
			}));
			System.out.println("RabbitMQ Server started");
			// any stream error message?
			StandardOutStreamForwarder errorStream = new StandardOutStreamForwarder(
					p.getErrorStream(), true);
	
			// any stream output message?
			StandardOutStreamForwarder outputStream = new StandardOutStreamForwarder(
					p.getInputStream(), false);
	
			// kick them off
			errorStream.start();
			outputStream.start();
		} catch (Exception e) {
			System.out.println("Something went wrong: " + e.toString());
		}

//		execCommand(command, new File(path));
	}

	// This method shutdown the server rabbitMQ
	public void stopServer() throws IOException {
		
		String[] command = { path + "\\rabbitmqctl.bat", "stop" };
		execCommand(command, null);


	}

	// This method starts the server rabbitMQ
	public void statusServer() throws IOException {
		
		String[] command = { path + "\\rabbitmqctl.bat", "status" };
		execCommand(command, null);
	}

	// This method launches the script rabbitmqctl.bat with 10 parameters to
	// set, you can also set less than 10 parameters as long as I never use
	// parameters are always passed something like ""
	// ex execScript("add_user", "mane", "password", "", "", "", "", "", "",
	// "");
	public void execScriptManualCommand(String[] parameter) throws IOException {

		if (parameter.length == 1) {
			
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0] };
				
				execCommand(command, null);
		}

		if (parameter.length == 2) {
			
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1] };

				execCommand(command, null);
		}

		if (parameter.length == 3) {
		
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2] };

				execCommand(command, null);
		}

		if (parameter.length == 4) {
			
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2], parameter[3] };

				execCommand(command, null);
		}

		if (parameter.length == 5) {
			
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2], parameter[3],
						parameter[4] };

				execCommand(command, null);
		}

		if (parameter.length == 6) {
		
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2], parameter[3],
						parameter[4], parameter[5] };

				execCommand(command, null);
		}

		if (parameter.length == 7) {
			
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2], parameter[3],
						parameter[4], parameter[5], parameter[6] };

				execCommand(command, null);
		}

		if (parameter.length == 8) {
			
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2], parameter[3],
						parameter[4], parameter[5], parameter[6], parameter[7] };

				execCommand(command, null);
		}

		if (parameter.length == 9) {
		
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2], parameter[3],
						parameter[4], parameter[5], parameter[6], parameter[7],
						parameter[8] };

				execCommand(command, null);
		}

		if (parameter.length == 10) {
			
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2], parameter[3],
						parameter[4], parameter[5], parameter[6], parameter[7],
						parameter[8], parameter[9] };

				execCommand(command, null);
		}

		if (parameter.length == 11) {
			
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2], parameter[3],
						parameter[4], parameter[5], parameter[6], parameter[7],
						parameter[8], parameter[9], parameter[10] };

				execCommand(command, null);
		}

		if (parameter.length == 12) {
	
				String[] command = { path + "\\rabbitmqctl.bat",
						parameter[0], parameter[1], parameter[2], parameter[3],
						parameter[4], parameter[5], parameter[6], parameter[7],
						parameter[8], parameter[9], parameter[10],
						parameter[11] };

				execCommand(command, null);
		}

	}

	// This method launches the script rabbitmqctl.bat and add_user

	public void execScriptAddUser(String name, String pass) throws IOException {

			String[] command = { path + "\\rabbitmqctl.bat", "add_user",
					name, pass };

			execCommand(command, null);

	}

	// This method launches the script rabbitmqctl.bat and delete_user

	public void execScriptDeleteUser(String name) throws IOException {

			String[] command = { path + "\\rabbitmqctl.bat",
					"delete_user", name };

			execCommand(command, null);
	}

	// This method launches the script rabbitmqctl.bat and change_password

	public void execScriptCangePassUser(String name, String newPass)
			throws IOException {

			String[] command = { path + "\\rabbitmqctl.bat",
					"change_password", name, newPass };

			execCommand(command, null);
	}

	// This method launches the script rabbitmqctl.bat and set_admin

	public void execScriptSetAdmin(String name) throws IOException {

			String[] command = { path + "\\rabbitmqctl.bat", "set_admin",
					name};

//			Runtime rt = Runtime.getRuntime();
//			Process proc = rt.exec(command);

			execCommand(command, null);
	}

	// This method launches the script rabbitmqctl.bat and clear_admin

	public void execScriptClearAdmin(String name) throws IOException {

			String[] command = { path + "\\rabbitmqctl.bat",
					"clear_admin", name };

			execCommand(command, null);
	}

	// This method launches the script rabbitmqctl.bat and add_vhost

	public void execScriptAddVhost(String vhost) throws IOException {

			String[] command = { path + "\\rabbitmqctl.bat", "add_vhost",
					vhost };

			execCommand(command, null);

	}

	// This method launches the script rabbitmqctl.bat and delete_vhost

	public void execScriptDeleteVhost(String vhost) throws IOException {

			String[] command = { path + "\\rabbitmqctl.bat",
					"delete_vhost", vhost };

			execCommand(command, null);
	}

	// This method launches the script rabbitmqctl.bat and set_permissions

	public void execScriptSetPermissions(String vhostPath, String user,
			String conf, String write, String read) throws IOException {

			String[] command = { path + "\\rabbitmqctl.bat",
					"set_permissions", "-p", vhostPath, user, 
					String.format(SET_PERMISSION_FORMAT, conf, write, read) };

			execCommand(command, null);

	}

	// This method launches the script rabbitmqctl.bat and clear_permissions

	public void execScriptClearPermissions(String vhostPath, String user)
			throws IOException {
		
			String[] command = { path + "\\rabbitmqctl.bat",
					"clear_permissions", "-p", vhostPath, user };
			
			execCommand(command, null);
	}

	
	
	public void execCommand(String[] command, File dir){
		try{
			System.out.print("Executing command::");
			for (String singleCommand : command)
				System.out.print(" " + singleCommand);
			System.out.println();
			
			Runtime rt = Runtime.getRuntime();
			Process proc = rt.exec(command,null,dir);
	
			// any stream error message?
			StandardOutStreamForwarder errorStream = new StandardOutStreamForwarder(
					proc.getErrorStream(), true);
	
			// any stream output message?
			StandardOutStreamForwarder outputStream = new StandardOutStreamForwarder(
					proc.getInputStream(), false);
	
			// kick them off
			errorStream.start();
			outputStream.start();
	
			// any error???
			// int exitVal = proc.waitFor();
			// System.out.println("ExitValue: " + exitVal);
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

}